<template>
  <div class="upload-container">
    <div 
      class="upload-area"
      @drop="handleDrop"
      @dragover="handleDragOver"
      @dragleave="handleDragLeave"
      @click="triggerFileInput"
      :class="{ 'drag-over': isDragOver }"
    >
      <input
        ref="fileInput"
        type="file"
        @change="handleFileSelect"
        style="display: none"
        :accept="acceptTypes"
      />
      <div class="upload-content">
        <div class="upload-icon">📁</div>
        <p class="upload-text">点击或拖拽文件到此处上传</p>
        <p class="upload-hint">支持大文件上传，自动分片处理、断点续传处理</p>
        <p class="upload-limits">最大支持 10GB，格式不限</p>
      </div>
    </div>

    <!-- 文件信息 -->
    <div v-if="selectedFile" class="file-info">
      <div class="file-header">
        <div class="file-name-section">
          <span class="file-name">{{ selectedFile.name }}</span>
          <span class="file-type">(文件类型：{{ getFileType(selectedFile.name) }})</span>
        </div>
        <button 
          class="cancel-btn" 
          @click="cancelUpload"
          v-if="uploading"
        >
          取消上传
        </button>
      </div>
      
      <div class="file-details">
        <span>大小: {{ formatFileSize(selectedFile.size) }}</span>
        <span>分片: {{ totalChunks }} 个</span>
        <span>哈希: {{ shortFileHash }}</span>
      </div>

      <!-- 总体进度 -->
      <div class="progress-section">
        <div class="progress-header">
          <span>总体进度</span>
          <span>{{ overallProgress.toFixed(1) }}%</span>
        </div>
        <div class="progress-bar">
          <div 
            class="progress-fill" 
            :style="{ width: `${overallProgress}%` }"
            :class="{ 'progress-error': uploadError }"
          ></div>
        </div>
        <div v-if="uploadError" class="error-message">
          ❌ {{ uploadError }}
        </div>
      </div>

      <!-- 分片进度 -->
      <div v-if="uploading && chunkProgress.length > 0" class="chunks-progress">
        <div class="chunks-header">
          <span>分片上传进度</span>
          <span>已完成 {{ completedChunksCount }}/{{ totalChunks }}</span>
        </div>
        <div class="chunks-grid">
          <div 
            v-for="chunk in visibleChunks" 
            :key="chunk.index"
            class="chunk-item"
            :class="{ 
              completed: chunk.progress === 100,
              error: chunk.error 
            }"
          >
            <div class="chunk-progress-bar">
              <div 
                class="chunk-progress-fill" 
                :style="{ width: `${chunk.progress}%` }"
              ></div>
            </div>
            <span class="chunk-label">分片 {{ chunk.index + 1 }}</span>
            <span v-if="chunk.error" class="chunk-error">❌</span>
          </div>
        </div>
        <div v-if="chunkProgress.length > 6" class="chunks-more">
          还有 {{ chunkProgress.length - 6 }} 个分片...
        </div>
      </div>

      <div class="action-buttons">
        <button 
          class="upload-btn primary"
          @click="startUpload"
          :disabled="uploading || uploadCompleted"
          v-if="!uploadCompleted"
        >
          {{ uploadButtonText }}
        </button>
        
        <button 
          class="upload-btn secondary"
          @click="resetUpload"
          v-if="uploadCompleted || uploadError"
        >
          上传新文件
        </button>

        <button 
          class="upload-btn secondary"
          @click="retryUpload"
          :disabled="uploading"
          v-if="uploadError"
        >
          重新上传
        </button>
      </div>
    </div>

    <!-- 上传结果 -->
    <div v-if="uploadResult" class="result-section">
      <div class="success-message">
        ✅ 文件上传成功！
      </div>
      <div class="result-info">
        <p><strong>文件名称:</strong> {{ uploadResult.fileName }}</p>
        <p><strong>文件大小:</strong> {{ formatFileSize(uploadResult.size) }}</p>
        <p><strong>上传时间:</strong> {{ new Date().toLocaleString() }}</p>
        <p v-if="uploadResult.url">
          <strong>访问地址:</strong> 
          <a :href="uploadResult.url" target="_blank">{{ uploadResult.url }}</a>
        </p>
      </div>
    </div>
  </div>
</template>

<script>
import { ref, computed, onUnmounted } from 'vue'
import axios from 'axios'
import FileUploader from '@/utils/upload.js'

export default {
  name: 'FileUpload',
  setup() {
    const fileInput = ref(null)
    const selectedFile = ref(null)
    const uploading = ref(false)
    const overallProgress = ref(0)
    const chunkProgress = ref([])
    const uploadResult = ref(null)
    const totalChunks = ref(0)
    const fileHash = ref('')
    const uploadError = ref('')
    const isDragOver = ref(false)
    const uploadCompleted = ref(false)

    const uploader = new FileUploader()
    let cancelToken = null

    const acceptTypes = ref('*/*')

    const uploadButtonText = computed(() => {
      if (uploading.value) return `上传中... ${overallProgress.value.toFixed(1)}%`
      return '开始上传'
    })

    const shortFileHash = computed(() => {
      return fileHash.value ? fileHash.value.substring(0, 8) + '...' : ''
    })

    const completedChunksCount = computed(() => {
      return chunkProgress.value.filter(chunk => chunk.progress === 100).length
    })

    const visibleChunks = computed(() => {
      return chunkProgress.value.slice(0, 6) // 只显示前6个分片
    })

    // 触发文件选择
    const triggerFileInput = () => {
      fileInput.value?.click()
    }

    // 处理文件选择
    const handleFileSelect = (event) => {
      const file = event.target.files[0]
      if (file) {
        setSelectedFile(file)
      }
    }

    // 设置选中的文件
    const setSelectedFile = (file) => {
      selectedFile.value = file
      uploadResult.value = null
      uploadError.value = ''
      overallProgress.value = 0
      chunkProgress.value = []
      uploadCompleted.value = false
      fileHash.value = ''
      
      // 计算文件哈希
      calculateFileHash(file)
    }

    // 计算文件哈希
    const calculateFileHash = async (file) => {
      try {
        fileHash.value = await uploader.calculateFileHashByContent(file)
      } catch (error) {
        console.warn('内容哈希计算失败，使用简单哈希:', error)
        fileHash.value = await uploader.calculateSimpleHash(file)
      }
    }

    // 处理拖拽
    const handleDragOver = (event) => {
      event.preventDefault()
      isDragOver.value = true
    }

    const handleDragLeave = (event) => {
      event.preventDefault()
      isDragOver.value = false
    }

    const handleDrop = (event) => {
      event.preventDefault()
      isDragOver.value = false
      const files = event.dataTransfer.files
      if (files.length > 0) {
        setSelectedFile(files[0])
      }
    }

    // 开始上传
    const startUpload = async () => {
      if (!selectedFile.value || uploading.value) return

      uploading.value = true
      uploadError.value = ''
      overallProgress.value = 0
      uploadResult.value = null
      uploadCompleted.value = false

      try {
        // 如果没有哈希，重新计算
        if (!fileHash.value) {
          await calculateFileHash(selectedFile.value)
        }
        
        // 创建分片
        const chunks = uploader.createFileChunks(selectedFile.value)
        totalChunks.value = chunks.length
        
        // 初始化分片进度
        chunkProgress.value = chunks.map((_, index) => ({
          index,
          progress: 0,
          error: false
        }))

        // 检查文件状态（断点续传）
        const fileStatus = await uploader.checkFileStatus(
          fileHash.value,
          selectedFile.value.name,
          totalChunks.value
        )
        console.log('文件状态检查结果:', fileStatus)

        // 如果文件已完全上传，直接返回
        if (fileStatus.message === '文件已存在') {
          uploadResult.value = {
            fileName: selectedFile.value.name,
            size: fileStatus.size,
            url: fileStatus.url || ''
          }
          overallProgress.value = 100
          uploadCompleted.value = true
          uploading.value = false
          return
        }

        // 获取已上传的分片索引列表
        let uploadedChunkIndexes = new Set()
        if (fileStatus.message === '存在未完成的上传') {
          // 从服务器获取已上传的分片
          uploadedChunkIndexes = new Set(fileStatus.uploadedChunks || [])
        } else {
          // 从本地存储获取已上传的分片（作为备用）
          const localProgress = uploader.loadProgressFromLocal(fileHash.value)
          if (localProgress && localProgress.uploadedChunks) {
            uploadedChunkIndexes = new Set(localProgress.uploadedChunks)
          }
        }
        
        console.log('已上传的分片索引:', Array.from(uploadedChunkIndexes))

        // 标记已上传的分片进度为100%
        uploadedChunkIndexes.forEach(index => {
          if (chunkProgress.value[index]) {
            chunkProgress.value[index].progress = 100
          }
        })

        // 更新初始总体进度
        if (uploadedChunkIndexes.size > 0) {
          overallProgress.value = (uploadedChunkIndexes.size / totalChunks.value) * 100
        }

        let completedChunks = uploadedChunkIndexes.size

        // 创建取消令牌
        cancelToken = uploader.createCancelToken()

        // 只上传未完成的分片
        const uploadPromises = chunks.map((chunk, index) => {
          // 如果分片已上传，跳过
          if (uploadedChunkIndexes.has(index)) {
            return Promise.resolve()
          }

          const chunkData = {
            chunk,
            hash: `${fileHash.value}-${index}`,
            index,
            fileHash: fileHash.value,
            fileName: selectedFile.value.name
          }

          return uploader.uploadChunk(chunkData, (progress) => {
            // 更新分片进度
            chunkProgress.value[index].progress = progress
            chunkProgress.value[index].error = false
            
            // 计算总体进度
            const baseProgress = (completedChunks / totalChunks.value) * 100
            const currentChunkProgress = (progress / 100) * (100 / totalChunks.value)
            overallProgress.value = Math.min(baseProgress + currentChunkProgress, 100)
            
            // 保存进度到本地存储
            const currentUploadedChunks = chunkProgress.value
              .filter(chunk => chunk.progress === 100)
              .map(chunk => chunk.index)
            uploader.saveProgressToLocal(fileHash.value, {
              fileName: selectedFile.value.name,
              uploadedChunks: currentUploadedChunks,
              totalChunks: totalChunks.value
            })
          }).then(() => {
            completedChunks++
            chunkProgress.value[index].progress = 100
          }).catch(error => {
            chunkProgress.value[index].error = true
            throw error
          })
        })

        await Promise.all(uploadPromises)
        
        // 合并文件
        const result = await uploader.mergeChunks(
          fileHash.value, 
          selectedFile.value.name, 
          totalChunks.value
        )
        
        uploadResult.value = result
        overallProgress.value = 100
        uploadCompleted.value = true

        // 清理本地存储的进度
        uploader.clearProgressFromLocal(fileHash.value)

      } catch (error) {
        console.error('上传失败:', error)
        if (axios.isCancel(error)) {
          uploadError.value = '上传已取消'
        } else {
          uploadError.value = error.message || '上传失败，请重试'
        }
      } finally {
        uploading.value = false
      }
    }

    // 取消上传
    const cancelUpload = () => {
      if (cancelToken) {
        cancelToken.cancel('用户取消上传')
      }
      uploading.value = false
      uploadError.value = '上传已取消'
    }

    // 重新上传
    const retryUpload = () => {
      uploadError.value = ''
      startUpload()
    }

    // 重置上传
    const resetUpload = () => {
      selectedFile.value = null
      uploadResult.value = null
      uploadError.value = ''
      overallProgress.value = 0
      chunkProgress.value = []
      uploadCompleted.value = false
      fileHash.value = ''
      if (fileInput.value) {
        fileInput.value.value = ''
      }
    }

    // 获取文件类型
    const getFileType = (fileName) => {
      const ext = fileName.split('.').pop().toLowerCase()
      const types = {
        'jpg': '图片', 'jpeg': '图片', 'png': '图片', 'gif': '图片',
        'pdf': 'PDF', 'doc': '文档', 'docx': '文档',
        'zip': '压缩包', 'rar': '压缩包', '7z': '压缩包',
        'mp4': '视频', 'avi': '视频', 'mov': '视频', 'txt': '文本'
      }
      return types[ext] || '未知文件'
    }

    // 格式化文件大小
    const formatFileSize = (bytes) => {
      if (bytes === 0) return '0 B'
      const k = 1024
      const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
      const i = Math.floor(Math.log(bytes) / Math.log(k))
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
    }

    // 组件卸载时取消上传
    onUnmounted(() => {
      if (uploading.value && cancelToken) {
        cancelToken.cancel('组件卸载')
      }
    })

    return {
      fileInput,
      selectedFile,
      uploading,
      overallProgress,
      chunkProgress,
      uploadResult,
      totalChunks,
      fileHash,
      uploadError,
      isDragOver,
      uploadCompleted,
      acceptTypes,
      uploadButtonText,
      shortFileHash,
      completedChunksCount,
      visibleChunks,
      triggerFileInput,
      handleFileSelect,
      handleDragOver,
      handleDragLeave,
      handleDrop,
      startUpload,
      cancelUpload,
      retryUpload,
      resetUpload,
      getFileType,
      formatFileSize
    }
  }
}
</script>

<style scoped>
/* 样式保持不变，与之前相同 */
.upload-container {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}

.upload-area {
  border: 2px dashed #ccc;
  border-radius: 12px;
  padding: 60px 20px;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
  background: #fafafa;
}

.upload-area:hover,
.upload-area.drag-over {
  border-color: #409eff;
  background: #f0f7ff;
  transform: translateY(-2px);
}

.upload-content {
  color: #666;
}

.upload-icon {
  font-size: 64px;
  margin-bottom: 20px;
  opacity: 0.7;
}

.upload-text {
  font-size: 18px;
  font-weight: 500;
  margin-bottom: 8px;
  color: #333;
}

.upload-hint {
  font-size: 14px;
  color: #999;
  margin-bottom: 4px;
}

.upload-limits {
  font-size: 12px;
  color: #ccc;
}

.file-info {
  margin-top: 24px;
  padding: 20px;
  border: 1px solid #e1e1e1;
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.file-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 16px;
}

.file-name-section {
  flex: 1;
}

.file-name {
  display: block;
  font-weight: 600;
  color: #333;
  font-size: 16px;
  margin-bottom: 4px;
  word-break: break-all;
}

.file-type {
  font-size: 12px;
  color: #666;
  background: #f5f5f5;
  padding: 2px 8px;
  border-radius: 12px;
}

.cancel-btn {
  padding: 6px 16px;
  border: 1px solid #ff4d4f;
  border-radius: 6px;
  background: #fff;
  color: #ff4d4f;
  cursor: pointer;
  font-size: 14px;
  white-space: nowrap;
}

.cancel-btn:hover {
  background: #ff4d4f;
  color: #fff;
}

.file-details {
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
  font-size: 14px;
  color: #666;
  flex-wrap: wrap;
}

.progress-section {
  margin-bottom: 24px;
}

.progress-header {
  display: flex;
  justify-content: space-between;
  margin-bottom: 12px;
  font-size: 14px;
  font-weight: 500;
}

.progress-bar {
  height: 12px;
  background: #f0f0f0;
  border-radius: 6px;
  overflow: hidden;
  position: relative;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #409eff, #52c41a);
  transition: width 0.3s ease;
  border-radius: 6px;
}

.progress-fill.progress-error {
  background: #ff4d4f;
}

.error-message {
  margin-top: 8px;
  padding: 8px 12px;
  background: #fff2f0;
  border: 1px solid #ffccc7;
  border-radius: 6px;
  color: #a8071a;
  font-size: 14px;
}

.chunks-progress {
  margin-bottom: 20px;
}

.chunks-header {
  display: flex;
  justify-content: space-between;
  margin-bottom: 12px;
  font-size: 14px;
  color: #666;
}

.chunks-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  gap: 8px;
  margin-bottom: 8px;
}

.chunk-item {
  padding: 8px;
  border: 1px solid #e1e1e1;
  border-radius: 6px;
  background: #fafafa;
  transition: all 0.3s ease;
}

.chunk-item.completed {
  border-color: #52c41a;
  background: #f6ffed;
}

.chunk-item.error {
  border-color: #ff4d4f;
  background: #fff2f0;
}

.chunk-progress-bar {
  height: 6px;
  background: #f0f0f0;
  border-radius: 3px;
  overflow: hidden;
  margin-bottom: 6px;
}

.chunk-progress-fill {
  height: 100%;
  background: #409eff;
  transition: width 0.3s ease;
  border-radius: 3px;
}

.chunk-item.completed .chunk-progress-fill {
  background: #52c41a;
}

.chunk-item.error .chunk-progress-fill {
  background: #ff4d4f;
}

.chunk-label {
  font-size: 11px;
  color: #666;
  display: block;
  text-align: center;
}

.chunk-error {
  font-size: 10px;
  display: block;
  text-align: center;
  margin-top: 2px;
}

.chunks-more {
  text-align: center;
  font-size: 12px;
  color: #999;
  font-style: italic;
}

.action-buttons {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.upload-btn {
  padding: 12px 24px;
  border: none;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
  flex: 1;
  min-width: 120px;
}

.upload-btn.primary {
  background: #409eff;
  color: white;
}

.upload-btn.primary:hover:not(:disabled) {
  background: #337ecc;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
}

.upload-btn.primary:disabled {
  background: #ccc;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

.upload-btn.secondary {
  background: #f5f5f5;
  color: #666;
  border: 1px solid #d9d9d9;
}

.upload-btn.secondary:hover {
  background: #e6f7ff;
  color: #409eff;
  border-color: #409eff;
}

.result-section {
  margin-top: 24px;
  padding: 20px;
  border: 1px solid #52c41a;
  border-radius: 12px;
  background: #f6ffed;
  box-shadow: 0 2px 8px rgba(82, 196, 26, 0.1);
}

.success-message {
  font-size: 16px;
  font-weight: 600;
  color: #52c41a;
  margin-bottom: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.result-info {
  font-size: 14px;
  color: #666;
}

.result-info p {
  margin: 8px 0;
  display: flex;
  align-items: center;
}

.result-info strong {
  color: #333;
  min-width: 80px;
  display: inline-block;
}

.result-info a {
  color: #409eff;
  text-decoration: none;
  word-break: break-all;
}

.result-info a:hover {
  text-decoration: underline;
}

@media (max-width: 768px) {
  .upload-container {
    padding: 16px;
  }
  
  .upload-area {
    padding: 40px 16px;
  }
  
  .file-header {
    flex-direction: column;
    gap: 12px;
  }
  
  .file-details {
    flex-direction: column;
    gap: 8px;
  }
  
  .action-buttons {
    flex-direction: column;
  }
  
  .chunks-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
</style>